home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / oasis / oasis1-1.lha / oasis-1.1 / kern.c < prev    next >
C/C++ Source or Header  |  1992-05-01  |  29KB  |  974 lines

  1. /*==========================================================================*
  2.     Oasis Alpha Version 1.1               (C) Copyright 1992 Fah-Chun Cheong
  3.     Revised: 5/1/92 by: fcc@eecs.umich.edu    and The University of Michigan
  4.     ------------------------------------------------------------------------
  5.     Permission to use, copy, modify, distribute, sell and resell Oasis Alpha
  6.     software and its documentation for any purpose and without fee is hereby
  7.     granted, provided that the authorship be appropriately credited and
  8.     acknowledged, and that the above copyright notice appear in all copies
  9.     and both the copyright notice and this permission notice appear in
  10.     supporting documentation. The author makes no representations about the
  11.     suitability of this software for any purpose. It is provided "as is"
  12.     without express or implied warranty. Oasis Alpha is free, caveat emptor!
  13.     ------------------------------------------------------------------------
  14.     To request Oasis Alpha source code:   oasis-alpha-request@eecs.umich.edu
  15.     To enroll in the mailing list:        oasis-alpha-request@eecs.umich.edu
  16.     To send bug reports:                  oasis-alpha-bugs@eecs.umich.edu
  17.     To discuss openly all matters Oasis:  oasis-alpha@eecs.umich.edu
  18.  *==========================================================================*/
  19. #include                <sys/types.h>
  20. #include                <sys/time.h>
  21. #include                <sys/resource.h>
  22. #include                <sys/socket.h>
  23. #include                <netinet/in.h>
  24. #include                <signal.h>
  25. #include                <fcntl.h>
  26. #ifdef  _AIX
  27. #include                <sys/select.h>
  28. #endif  _AIX
  29. #include                "system.h"
  30.  
  31. #ifdef  SPARC
  32. #define TWO             2
  33. #else
  34. #define TWO             0
  35. #endif  SPARC
  36.  
  37. #ifndef KERN_BUG
  38. #define tracer(s,sz,buf)
  39. #define print1(s,a)
  40. #else
  41. #define print1(s,a)     printf(s, a)
  42. #endif  KERN_BUG
  43.  
  44. #define TNO             64
  45. #define STACKSZ         (1024 *  100)
  46. #define HEAPSZ          (1024 * 1000)
  47. #define BREAKSZ         (1024 *  800)
  48. #define MESGSZ          (1024 *  200)
  49.  
  50. #define new(arg)        (*(u_long *) arg & 0x0003)
  51. #define link(arg,qtr,q) (*qtr = *(u_long *) arg,\
  52.                          *(u_long *) arg = (u_long) qtr,\
  53.                          *--q = arg,\
  54.                          qtr += szof(qtr))
  55. #define move(arg,qtr,q) (new(arg) ? link(arg, qtr, q) : NUL)
  56. #define copy(arg,qtr,q) (arg ? (move(arg, qtr, q), *(u_long *) arg) : NUL)
  57. #define swizzle(arg,ho) (arg ? arg + ho : NUL)
  58. #define max(m,n)        (m > n ? m : n)
  59.  
  60. extern  u_long          cno;
  61. extern  long           *ctab[];
  62. extern  u_long        **dtab[];
  63. extern  u_long          hno;
  64. extern  Host            htab[];
  65.  
  66. Space                   space;
  67. u_long                 *root;
  68.  
  69. static  u_long         *hook[2];
  70. static  struct sigvec   svec   = { on_arrival, 0, SV_ONSTACK };
  71. static  struct sigstack sstack = { NUL, 0 };
  72. static  int             ssock  = 3;
  73. static  Thread          ttab[TNO];
  74. static  Thread        **qhead;
  75. static  Thread        **qtail;
  76. static  int             qno;
  77.  
  78. static  u_long         *vmap[] = {
  79.        (u_long *)       collect,
  80.        (u_long *)       mcret,
  81.        (u_long *)       msend,
  82.        (u_long *)       mdone,
  83.        (u_long *)       mquit,
  84.        (u_long *)       mrecv,
  85.        (u_long *)       cwait,
  86.        (u_long *)       cpost,
  87.        (u_long *)       zero,
  88.        (u_long *)       drem,
  89.        (u_long *)       iceil,
  90.        (u_long *)       ifloor,
  91.        (u_long *)       iround,
  92.        (u_long *)       itrunca,
  93.        (u_long *)       ffloat,
  94.        (u_long *)       sqrt,
  95.        (u_long *)       sin,
  96.        (u_long *)       cos,
  97.        (u_long *)       tan,
  98.        (u_long *)       asin,
  99.        (u_long *)       acos,
  100.        (u_long *)       atan,
  101.        (u_long *)       sinh,
  102.        (u_long *)       cosh,
  103.        (u_long *)       tanh,
  104.        (u_long *)       asinh,
  105.        (u_long *)       acosh,
  106.        (u_long *)       atanh,
  107.        (u_long *)       log10,
  108.        (u_long *)       logb,
  109.        (u_long *)       log,
  110.        (u_long *)       log1p,
  111.        (u_long *)       pow,
  112.        (u_long *)       exp,
  113.        (u_long *)       expm1,
  114.        (u_long *)       dbug
  115. };
  116.  
  117. static  struct rusage   gc_ru1, gc_ru2;
  118. static  long            gc_time_u;
  119. static  long            gc_time_s;
  120.  
  121. static  struct rusage   ru1, ru2;
  122. static  struct timeval  tm1, tm2;
  123. static  struct timezone tz;
  124. static  long            time_u;
  125. static  long            time_s;
  126. static  long            time_e;
  127.  
  128. static  int             gcno;
  129. static  int             thno;
  130. static  int             rpcno;
  131.  
  132. void    init_kern(n)
  133. int     n;
  134. {
  135.         int     i;
  136.  
  137.         qno   = n + 2;
  138.         qhead = (Thread **) calloc(qno, sizeof(Thread *));
  139.         qtail = (Thread **) calloc(qno, sizeof(Thread *));
  140.  
  141.         qhead[0] = &ttab[0];
  142.         for (i = 1; i < TNO; i++)
  143.             ttab[i-1].next = &ttab[i];
  144.         qtail[0] = &ttab[TNO - 1];
  145.  
  146.         space.heap = (u_long *) malloc(HEAPSZ * 4 * 2);
  147.         space.next = space.heap + HEAPSZ;
  148.         if (space.heap == NULL) {
  149.             error0("System out of memory\n");
  150.             exit(-1);
  151.         }
  152.         space.hp = space.heap;
  153.         space.bp = space.heap + BREAKSZ;
  154.         dtab[0]  = vmap;
  155.         hook[0]  = (u_long *) done;
  156.         hook[1]  = (u_long *) quit;
  157.  
  158.         signal(SIGQUIT, on_fault);
  159.         signal(SIGILL,  on_fault);
  160.         signal(SIGTRAP, on_fault);
  161.         signal(SIGIOT,  on_fault);
  162.         signal(SIGEMT,  on_fault);
  163.         signal(SIGBUS,  on_fault);
  164.         signal(SIGSEGV, on_fault);
  165.         signal(SIGSYS,  on_fault);
  166.  
  167.         sstack.ss_sp = (char *) malloc(STACKSZ * 4) + STACKSZ*2;
  168.         sstack.ss_onstack = 0;
  169.         sigstack(&sstack, 0);
  170.         sigvec(SIGIO, &svec, 0);
  171.  
  172.         if (fcntl(ssock, F_SETOWN, getpid()) < 0)
  173.             perror("F_SETOWN error");
  174.         if (fcntl(ssock, F_SETFL,  FASYNC) < 0)
  175.             perror("F_SETFL FASYNC error");
  176. }
  177.  
  178. void    stat_on()
  179. {
  180.         gcno  = 0;
  181.         thno  = 1;
  182.         rpcno = 0;
  183.  
  184.         gc_time_u = 0;
  185.         gc_time_s = 0;
  186.  
  187.         tz.tz_minuteswest = 0;
  188.         tz.tz_dsttime = 0;
  189.         gettimeofday(&tm1, &tz);
  190.         getrusage(0, &ru1);
  191. }
  192.  
  193. void    stat_off()
  194. {
  195.         getrusage(0, &ru2);
  196.         gettimeofday(&tm2, &tz);
  197.         time_u = (ru2.ru_utime.tv_sec  - ru1.ru_utime.tv_sec)  * 1000000
  198.                + (ru2.ru_utime.tv_usec - ru1.ru_utime.tv_usec) + 1;
  199.         time_s = (ru2.ru_stime.tv_sec  - ru1.ru_stime.tv_sec)  * 1000000
  200.                + (ru2.ru_stime.tv_usec - ru1.ru_stime.tv_usec) + 1;
  201.         time_e = (tm2.tv_sec           - tm1.tv_sec)  * 1000000
  202.                + (tm2.tv_usec          - tm1.tv_usec) + 1;
  203.  
  204.         fprintf(stderr, "%.1fu %.1fs %d:%02d %d%% %d+%dio %dpf+%dw  [%.1fu %.1fs %dgc] %dth %drpc\n",
  205.                (double) time_u / 1000000.0, (double) time_s / 1000000.0,
  206.                time_e / 60000000, time_e / 1000000 % 60,
  207.                (int) ((time_u + time_s) * 100.0 / time_e),
  208.                ru2.ru_inblock - ru1.ru_inblock, ru2.ru_oublock - ru1.ru_oublock,
  209.                ru2.ru_majflt  - ru1.ru_majflt,  ru2.ru_nswap   - ru1.ru_nswap,
  210.                (double) gc_time_u / 1000000.0, (double) gc_time_s / 1000000.0,
  211.                gcno, thno, rpcno);
  212. }
  213.  
  214. u_long  run(buf, size, start)
  215. char   *buf;
  216. int     size;
  217. u_long *start;
  218. {
  219.         Thread         *thread;
  220.         int             mask;
  221.  
  222.         mask = sigblock(sigmask(SIGIO));
  223.         thread = qhead[0];
  224.         tmove(0, 1);
  225.         thread->stack = (u_long *) malloc(STACKSZ * 4);
  226.         thread->mp    = thread->stack - 1;
  227.         thread->sb    = thread->stack + STACKSZ;
  228.         thread->sp    = thread->sb - 2;
  229.         thread->pc    = start;
  230.         thread->hook  = hook;
  231.         thread->mbuf  = NUL;
  232.         thread->sp[1] = (u_long) root;
  233.  
  234. #if     !defined(M68K) && !defined(I386)
  235.         thread->sp    = thread->sb;
  236. #endif  !M68K && !I386
  237.         sigsetmask(mask);
  238.  
  239.         stat_on();
  240.         space.hp = call(dtab, &space, thread);
  241.         stat_off();
  242.  
  243.         if (buf && !*space.hp)
  244.             bcopy(thread->sb - atoi(buf) - 2, buf + size, atoi(buf) * sizeof(u_long));
  245.  
  246.         mask = sigblock(sigmask(SIGIO));
  247.         free(thread->stack);
  248.         tmove(1, 0);
  249.         sigsetmask(mask);
  250.         return *space.hp;
  251. }
  252.  
  253. VOID    on_fault()
  254. {
  255.         int     i;
  256.  
  257.         fprintf(stderr, "\n[pid %d] died:\n", getpid());
  258.         for (i = 1; i < qno; i++) {
  259.              Thread *thread = qhead[i];
  260.              if (thread) fprintf(stderr, "[%d]:", i);
  261.              for (; thread; thread = thread->next)
  262.                  fprintf(stderr, "\t0x%08x", thread);
  263.              if (qhead[i]) putc('\n', stderr);
  264.         }
  265.         fprintf(stderr, "\nCore dumped:\n");
  266.         fprintf(stderr, "heap  = 0x%08x\n", space.heap);
  267.         fprintf(stderr, "hp    = 0x%08x\n", space.hp);
  268.         fprintf(stderr, "bp    = 0x%08x\n", space.bp);
  269.         fprintf(stderr, "stack = 0x%08x\n", qhead[1]->stack);
  270.         fprintf(stderr, "sb    = 0x%08x\n", qhead[1]->sb);
  271.         fprintf(stderr, "sp    = 0x%08x\n", qhead[1]->sp);
  272.         fprintf(stderr, "pc    = 0x%08x\n", qhead[1]->pc);
  273.         fprintf(stderr, "hook  = 0x%08x\n", qhead[1]->hook);
  274.         fprintf(stderr, "root  = 0x%08x\n", root);
  275.  
  276.         for (i = 1; i < 32; i++) {
  277.             if (i % 4 == 1) fprintf(stderr, "\n[%08x]  ", qhead[1]->sb - i);
  278.             fprintf(stderr,  "%08x  ", qhead[1]->sb[-i]);
  279.         }
  280.         putc('\n', stderr);
  281.         for (i = 0; i < 32; i++) {
  282.             if (i % 4 == 0) fprintf(stderr, "\n[%08x]  ", space.heap + i);
  283.             fprintf(stderr, "%08x  ", space.heap[i]);
  284.         }
  285.         putc('\n', stderr);
  286.         exit(0);
  287. }
  288.  
  289. VOID    on_arrival()
  290. {
  291.         struct timeval  timeout;
  292.         fd_set          fdset;
  293.         Socket          client;
  294.         int             csock;
  295.         int             sz = sizeof(client);
  296.         u_long         *buf;
  297.         u_long          size;
  298.  
  299.         print1("[pid %d] !\n", getpid());
  300.         FD_ZERO(&fdset);
  301.         FD_SET(ssock, &fdset);
  302.         timeout.tv_sec  = 0L;
  303.         timeout.tv_usec = 0L;
  304.         switch (select(ssock + 1, &fdset, (fd_set *) 0, (fd_set *) 0, &timeout)) {
  305.             case  1:    break;
  306.             case  0:    return;
  307.             default:    perror("selecting stream socket");
  308.         }
  309.         if ((csock = accept(ssock, (Sock *) &client, &sz)) < 0) {
  310.             perror("accepting stream connection");
  311.             exit(-1);
  312.         }
  313.         readn(csock, &size, sizeof(u_long));
  314.         size = ntohl(size);
  315.         buf  = (u_long *) malloc(size);
  316.         buf[SIZE] = size;
  317.         readn(csock, buf + 1, size - sizeof(u_long));
  318.         close(csock);
  319.  
  320.         reorder(buf, size);
  321.         switch (buf[MTYPE]) {
  322.             case MSEND: qhead[0]->mbuf = buf;
  323.                         tmove(0, 1);
  324.                         tracer("received request", size, buf);  break;
  325.             case MDONE: *(u_long *) buf[XID] = (u_long) buf;
  326.                         tracer("received reply",   size, buf);  break;
  327.             case MQUIT: *(u_long *) buf[XID] = (u_long) buf;
  328.                         tracer("received failure", size, buf);  break;
  329.         }
  330. }
  331.  
  332. void    reorder(buf, size)
  333. u_long *buf;
  334. u_long  size;
  335. {
  336.         if (buf[ENDIAN] != 0xbeeffeed) {
  337.             char  *ptr = (char *) buf + 4;
  338.             for (; ptr < (char *) buf + size; ptr += 4) {
  339.                 char c0 = ptr[0];
  340.                 char c1 = ptr[1];
  341.                 ptr[0]  = ptr[3];
  342.                 ptr[3]  = c0;
  343.                 ptr[1]  = ptr[2];
  344.                 ptr[2]  = c1;
  345.             }
  346.         }
  347. }
  348.  
  349. u_long  create(addr, port, port0, buf, size)
  350. u_long  addr;
  351. u_long  port;
  352. u_long  port0;
  353. u_long *buf;
  354. u_long  size;
  355. {
  356.         Socket  server;
  357.         int     csock;
  358. #ifdef  MESG_BUG
  359.         int     i;
  360.         for (i = 0; i < size / 4; i++)
  361.             printf("[%04d]  0x%08x  (%d)\n", i, buf[i], buf[i]);
  362. #endif  MESG_BUG
  363.  
  364.         if ((csock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  365.             perror("opening stream socket");
  366.             exit(-1);
  367.         }
  368.         server.sin_family      = AF_INET;
  369.         server.sin_addr.s_addr = htonl(addr);
  370.         server.sin_port        = htons((u_short) port);
  371.  
  372.         if (connect(csock, (Sock *) &server, sizeof(server)))
  373.             perror("connecting stream socket");
  374.         else {
  375.             port0 = htonl(port0);
  376.             writn(csock, &port0, sizeof(u_long));
  377.             writn(csock, buf,    size);
  378.             readn(csock, &port0, sizeof(u_long));
  379.             close(csock);
  380.             port0 = ntohl(port0);
  381.         }
  382.         return port0;
  383. }
  384.  
  385. void    transmit(addr, port, buf, size)
  386. u_long  addr;
  387. u_long  port;
  388. u_long *buf;
  389. u_long  size;
  390. {
  391.         Socket  server;
  392.         int     csock;
  393. #ifdef  MESG_BUG
  394.         int     i;
  395.         for (i = 0; i < size / 4; i++)
  396.             printf("[%04d]  0x%08x  (%d)\n", i, buf[i], buf[i]);
  397. #endif  MESG_BUG
  398.  
  399.         if ((csock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  400.             perror("opening stream socket");
  401.             exit(-1);
  402.         }
  403.         server.sin_family      = AF_INET;
  404.         server.sin_addr.s_addr = htonl(addr);
  405.         server.sin_port        = htons((u_short) port);
  406.  
  407.         if (connect(csock, (Sock *) &server, sizeof(server)))
  408.             perror("connecting stream socket");
  409.         else writn(csock, buf, size);
  410.         close(csock);
  411. }
  412.  
  413. Space  *collect(sp, pc)
  414. u_long *sp;
  415. u_long *pc;
  416. {
  417.         u_long *ptr = space.next;
  418.         u_long *qtr = ptr;
  419.         u_long *p   = ptr + HEAPSZ;
  420.         u_long *q   = ptr + HEAPSZ;
  421.         Thread *tp;
  422.         int     mask;
  423.         int     i;
  424.  
  425.         getrusage(0, &gc_ru1);
  426.  
  427. #ifdef  KERN_BUG
  428.         printf("Garbage collecting...  ");
  429.         fflush(stdout);
  430. #endif  KERN_BUG
  431.  
  432.         mask = sigblock(sigmask(SIGIO));
  433.         qhead[1]->sp = sp;
  434.         qhead[1]->pc = pc;
  435.         for (i = 1; i < qno; i++)
  436.             if (tp = qhead[i])
  437.                 do  if (!tp->mbuf)
  438.                     qtr = trace(tp, qtr, &q);
  439.                 while (tp = tp->next);
  440.  
  441.         space.hp = traverse(ptr, qtr, p, &q);
  442.         space.bp = ptr + BREAKSZ;
  443.         root = (u_long *) root[0];
  444.         space.next = space.heap;
  445.         space.heap = ptr;
  446.         sigsetmask(mask);
  447.  
  448. #ifdef  KERN_BUG
  449.         printf("%d bytes (%d%%) used, %d bytes (%d%%) free.\n",
  450.                (space.hp - space.heap) * 4, (space.hp - space.heap) * 100 / BREAKSZ,
  451.                (space.bp - space.hp)   * 4, (space.bp - space.hp)   * 100 / BREAKSZ);
  452. #endif  KERN_BUG
  453.  
  454.         getrusage(0, &gc_ru2);
  455.         gc_time_u += (gc_ru2.ru_utime.tv_sec  - gc_ru1.ru_utime.tv_sec)  * 1000000
  456.                   +  (gc_ru2.ru_utime.tv_usec - gc_ru1.ru_utime.tv_usec) + 1;
  457.         gc_time_s += (gc_ru2.ru_stime.tv_sec  - gc_ru1.ru_stime.tv_sec)  * 1000000
  458.                   +  (gc_ru2.ru_stime.tv_usec - gc_ru1.ru_stime.tv_usec) + 1;
  459.         gcno++;
  460.         return &space;
  461. }
  462.  
  463. u_long *trace(tp, qtr, qp)
  464. Thread *tp;
  465. u_long *qtr;
  466. u_long**qp;
  467. {
  468.         u_long *sb = tp->sb;
  469.         u_long *sp = tp->sp;
  470.         u_long *pc = tp->pc - 2 - TWO;
  471.         u_long *q  = *qp;
  472.  
  473.         if (tp != qhead[1])
  474.             pc -= pc[-1];
  475.  
  476.         while (sp < sb) {
  477.             long   *cp = (long *) pc + 2 + TWO;
  478.             u_long *gp;
  479.  
  480.             for (; *cp >= 0; cp++)
  481.                 sp[*cp] = copy(sp[*cp], qtr, q);
  482.  
  483.             pc = (u_long *) sp[-*cp - 1];
  484.             gp = (u_long *) sp[-*cp];
  485.             sp[-*cp++] = copy((u_long) gp, qtr, q);
  486.  
  487.             for (; *cp >= 0; cp += 2)
  488.                 if (gp[cp[1]] == T_POINTER)
  489.                     sp[*cp] = copy(sp[*cp], qtr, q);
  490.             sp += -*cp;
  491.         }
  492.         *qp = q;
  493.         return qtr;
  494. }
  495.  
  496. u_long *traverse(ptr, qtr, p, qp)
  497. u_long *ptr;
  498. u_long *qtr;
  499. u_long *p;
  500. u_long**qp;
  501. {
  502.         u_long *q = *qp;
  503.  
  504.         while (ptr < qtr) {
  505.             u_long *hp = (u_long *) *--p;
  506.  
  507.             switch (idof(*hp)) {
  508.                 case I_HANDLE:  ptr[1] = hp[1];
  509.                                 ptr[2] = hp[2];
  510.                                 ptr[3] = hp[3];
  511.                                 ptr   += 4;                     break;
  512.                 case I_LISTC:
  513.                 case I_LISTI:
  514.                 case I_LISTF:   ptr[1] = hp[1];
  515.                                 ptr[2] = copy(hp[2], qtr, q);
  516.                                 ptr   += 3;                     break;
  517.                 case I_LISTP:   ptr[1] = copy(hp[1], qtr, q);
  518.                                 ptr[2] = copy(hp[2], qtr, q);
  519.                                 ptr   += 3;                     break;
  520.                 case I_ARRAYC:
  521.                 case I_ARRAYI:
  522.                 case I_ARRAYF:{ int i = 1;
  523.                                 for (; i < szof(*hp); i++)      ptr[i] = hp[i];
  524.                                 ptr += i;                       break; }
  525.                 case I_ARRAYP:{ int i = 1;
  526.                                 for (; i < hp[1] + 2; i++)      ptr[i] = hp[i];
  527.                                 for (; i < szof(*hp); i++)      ptr[i] = copy(hp[i], qtr, q);
  528.                                 ptr += i;                       break; }
  529.  
  530.                 default:      { long *cp = ctab[idof(*hp)];
  531.                                 for (;     *cp >= 0; cp++)      ptr[*cp] = hp[*cp];
  532.                                 for (cp++; *cp >= 0; cp++)      ptr[*cp] = copy(hp[*cp], qtr, q);
  533.                                 for (cp++; *cp >= 0; cp += 2)   ptr[*cp] = hp[cp[1]] == T_POINTER
  534.                                                                          ? copy(hp[*cp], qtr, q)
  535.                                                                          : hp[*cp];
  536.                                 ptr += szof(*hp); }
  537.             }
  538.         }
  539.         *qp = q;
  540.         return qtr;
  541. }
  542.  
  543. u_long  marshal(buf, ptr, sp, arity)
  544. u_long *buf;
  545. u_long *ptr;
  546. u_long *sp;
  547. u_long  arity;
  548. {
  549.         u_long *qtr = ptr + arity*2;
  550.         u_long *p   = buf + MESGSZ;
  551.         u_long *q   = buf + MESGSZ;
  552.         int     i;
  553.  
  554.         for (i = 0; i < arity; i++) {
  555.             u_long  tag = ptr[i] = sp[arity + i];
  556.             u_long  arg = ptr[arity + i] = sp[i];
  557.             if (tag == T_POINTER)
  558.                 ptr[arity + i] = copy(arg, qtr, q);
  559.         }
  560.         qtr = traverse(ptr + arity*2, qtr, p, &q);
  561.  
  562.         while (q < p) {
  563.             u_long *hp = (u_long *) *q++;
  564.             *hp = *(u_long *) *hp;
  565.         }
  566.         return (qtr - buf) * 4;
  567. }
  568.  
  569. void    umarshal(buf, ptr, sp, arity)
  570. u_long *buf;
  571. u_long *ptr;
  572. u_long *sp;
  573. u_long  arity;
  574. {
  575.         u_long *qtr = (u_long *) ((u_long) buf + buf[SIZE]);
  576.         u_long  sz  = arity*2*4 + (ptr - buf)*4;
  577.         u_long *hp  = (u_long *) alloc(buf[SIZE] - sz);
  578.         u_long  ho  = (u_long) hp - buf[START] - sz;
  579.         int     i;
  580.  
  581.         for (i = 0; i < arity; i++)
  582.             sp[i] = ptr[i] == T_POINTER
  583.                   ? swizzle(ptr[arity + i], ho)
  584.                   : ptr[arity + i];
  585.         ptr += arity * 2;
  586.  
  587.         while (ptr < qtr) {
  588.             sz = szof(ptr);
  589.             hp[0] = ptr[0];
  590.  
  591.             switch (idof(ptr)) {
  592.                 case I_HANDLE:  hp[1] = ptr[1];
  593.                                 hp[2] = ptr[2];
  594.                                 hp[3] = ptr[3];                                                 break;
  595.                 case I_LISTC:
  596.                 case I_LISTI:
  597.                 case I_LISTF:   hp[1] = ptr[1];
  598.                                 hp[2] = swizzle(ptr[2], ho);                                    break;
  599.                 case I_LISTP:   hp[1] = swizzle(ptr[1], ho);
  600.                                 hp[2] = swizzle(ptr[2], ho);                                    break;
  601.                 case I_ARRAYC:
  602.                 case I_ARRAYI:
  603.                 case I_ARRAYF:  for (i = 1; i < sz; i++)        hp[i] = ptr[i];                 break;
  604.                 case I_ARRAYP:  for (i = 1; i < ptr[1] +2; i++) hp[i] = ptr[i];
  605.                                 for (; i < sz; i++)             hp[i] = swizzle(ptr[i], ho);    break;
  606.  
  607.                 default:      { long *cp = ctab[idof(ptr)];
  608.                                 for (;     *cp >= 0; cp++)      hp[*cp] = ptr[*cp];
  609.                                 for (cp++; *cp >= 0; cp++)      hp[*cp] = swizzle(ptr[*cp], ho);
  610.                                 for (cp++; *cp >= 0; cp += 2)   hp[*cp] = ptr[cp[1]] == T_POINTER
  611.                                                                         ? swizzle(ptr[*cp], ho)
  612.                                                                         : ptr[*cp]; }
  613.             }
  614.             hp  += sz;
  615.             ptr += sz;
  616.         }
  617. }
  618.  
  619. void    mcret(handle)
  620. u_long *handle;
  621. {
  622.         u_long *buf;
  623.         u_long  size;
  624.         u_long  sp[2];
  625.         int     mask;
  626.         int     i = -1;
  627.  
  628.         mask = sigblock(sigmask(SIGIO));
  629.         if (handle[2] != INADDR_ANY)
  630.             do  if (++i == hno) {
  631.                 error0("Internet address not in hosts list\n");
  632.                 exit(-1);
  633.                 }
  634.             while (handle[2] != htab[i].addr);
  635.         else {
  636.             i = pick(hno);
  637.             handle[2] = htab[i].addr;
  638.         }
  639.         sp[0] = (u_long) handle;
  640.         sp[1] = T_POINTER;
  641.         buf   = (u_long *) malloc(MESGSZ * 4);
  642.         size  = marshal(buf, buf + HEADSZ, sp, 1);
  643.  
  644.         buf[SIZE]   = htonl(size);
  645.         buf[ENDIAN] = 0xbeeffeed;
  646.         buf[START]  = (u_long) buf;
  647.         buf[MTYPE]  = MCRET;
  648.         buf[ADDR]   = 0;
  649.         buf[PORT]   = 0;
  650.         buf[XID]    = 0;
  651.         buf[MID]    = 0;
  652.         buf[INO]    = 0;
  653.         buf[ONO]    = 0;
  654.  
  655.         handle[0] = H_HANDLE;
  656.         handle[3] = create(htab[i].addr, htab[i].port, handle[3], buf, size);
  657.         free(buf);
  658.         sigsetmask(mask);
  659. }
  660.  
  661. void    msend(handle, sp)
  662. u_long *handle;
  663. u_long *sp;
  664. {
  665.         u_long *buf;
  666.         u_long *ptr;
  667.         u_long  size;
  668.         int     mask;
  669.         int     i;
  670.  
  671.         mask = sigblock(sigmask(SIGIO));
  672.         buf = (u_long *) malloc(MESGSZ * 4);
  673.         ptr = buf + HEADSZ;
  674.         for (i = 0; i < sp[2]; i++)
  675.             ptr[i] = sp[i + 3];
  676.  
  677.         size = marshal(buf, ptr + sp[2], sp + 3 + sp[2], sp[1]);
  678.         buf[SIZE]   = htonl(size);
  679.         buf[ENDIAN] = 0xbeeffeed;
  680.         buf[START]  = (u_long) buf;
  681.         buf[MTYPE]  = MSEND;
  682.         buf[ADDR]   = root[2];
  683.         buf[PORT]   = root[3];
  684.         buf[XID]    = (u_long) ++qhead[1]->mp;
  685.         buf[MID]    = sp[0];
  686.         buf[INO]    = sp[1];
  687.         buf[ONO]    = sp[2];
  688.  
  689.         rpcno++;
  690.         *qhead[1]->mp = NUL;
  691.         tracer("sending request", size, buf);
  692.         transmit(handle[2], handle[3], buf, size);
  693.         tracer("...sent request", size, buf);
  694.         free(buf);
  695.         sigsetmask(mask);
  696. }
  697.  
  698. u_long *mdone(hp)
  699. u_long *hp;
  700. {
  701.         u_long *sp = qhead[1]->sb - qhead[1]->ono;
  702.         u_long *buf;
  703.         u_long  size;
  704.         int     mask;
  705.  
  706.         mask = sigblock(sigmask(SIGIO));
  707.         buf  = (u_long *) malloc(MESGSZ * 4);
  708.         size = marshal(buf, buf + HEADSZ, sp, qhead[1]->ono);
  709.  
  710.         buf[SIZE]   = htonl(size);
  711.         buf[ENDIAN] = 0xbeeffeed;
  712.         buf[START]  = (u_long) buf;
  713.         buf[MTYPE]  = MDONE;
  714.         buf[ADDR]   = qhead[1]->addr;
  715.         buf[PORT]   = qhead[1]->port;
  716.         buf[XID]    = (u_long) qhead[1]->xid;
  717.         buf[MID]    = 0;
  718.         buf[INO]    = 0;
  719.         buf[ONO]    = qhead[1]->ono;
  720.  
  721.         tracer("sending reply", size, buf);
  722.         transmit(qhead[1]->addr, qhead[1]->port, buf, size);
  723.         tracer("...sent reply", size, buf);
  724.         free(qhead[1]->stack);
  725.         free(buf);
  726.         tmove(1, 0);
  727.  
  728.         space.hp = hp;
  729.         *space.hp = (u_long) twait(mask);
  730.         sigsetmask(mask);
  731.         return space.hp;
  732. }
  733.  
  734. u_long *mquit(hp)
  735. u_long *hp;
  736. {
  737.         u_long *buf;
  738.         u_long  size = HEADSZ * 4;
  739.         int     mask;
  740.  
  741.         mask = sigblock(sigmask(SIGIO));
  742.         buf  = (u_long *) malloc(HEADSZ * 4);
  743.  
  744.         buf[SIZE]   = htonl(size);
  745.         buf[ENDIAN] = 0xbeeffeed;
  746.         buf[START]  = (u_long) buf;
  747.         buf[MTYPE]  = MQUIT;
  748.         buf[ADDR]   = qhead[1]->addr;
  749.         buf[PORT]   = qhead[1]->port;
  750.         buf[XID]    = (u_long) qhead[1]->xid;
  751.         buf[MID]    = 0;
  752.         buf[INO]    = 0;
  753.         buf[ONO]    = 0;
  754.  
  755.         tracer("sending failure", size, buf);
  756.         transmit(qhead[1]->addr, qhead[1]->port, buf, size);
  757.         tracer("...sent failure", size, buf);
  758.         free(qhead[1]->stack);
  759.         free(buf);
  760.         tmove(1, 0);
  761.  
  762.         space.hp = hp;
  763.         *space.hp = (u_long) twait(mask);
  764.         sigsetmask(mask);
  765.         return space.hp;
  766. }
  767.  
  768. u_long *mrecv(hp, sp)
  769. u_long *hp;
  770. u_long *sp;
  771. {
  772.         u_long *buf;
  773.         int     mask;
  774.  
  775.         mask = sigblock(sigmask(SIGIO));
  776.         while (!*qhead[1]->mp) {
  777.             print1("[pid %d] pending reply...\n", getpid());
  778.             sigpause(mask);
  779.         }
  780.         buf = (u_long *) *qhead[1]->mp--;
  781.         space.hp = hp;
  782.         if (buf[MTYPE] == MDONE)
  783.             umarshal(buf, buf + HEADSZ, sp, buf[ONO]);
  784.         *space.hp = buf[MTYPE];
  785.         free(buf);
  786.         sigsetmask(mask);
  787.         return space.hp;
  788. }
  789.  
  790. void    tinit()
  791. {
  792.         u_long *buf = qhead[1]->mbuf;
  793.         u_long *ptr = buf + HEADSZ;
  794.         int     mask;
  795.         int     i;
  796.  
  797.         mask = sigblock(sigmask(SIGIO));
  798.         qhead[1]->stack = (u_long *) malloc(STACKSZ * 4);
  799.         qhead[1]->mp = qhead[1]->stack - 1;
  800.         qhead[1]->sb = qhead[1]->stack + STACKSZ - buf[ONO];
  801.         qhead[1]->sp = qhead[1]->sb - max(buf[INO], buf[ONO]);
  802.         qhead[1]->pc = dtab[idof(root)][buf[MID]];
  803.  
  804.         qhead[1]->hook = hook - TWO;
  805.         qhead[1]->mbuf = NUL;
  806.         qhead[1]->addr = buf[ADDR];
  807.         qhead[1]->port = buf[PORT];
  808.         qhead[1]->xid  = buf[XID];
  809.         qhead[1]->ono  = buf[ONO];
  810.  
  811.         for (i = 0; i < buf[ONO]; i++)
  812.             qhead[1]->sb[i] = ptr[i];
  813.  
  814.         umarshal(buf, ptr + buf[ONO], qhead[1]->sp, buf[INO]);
  815.         *--qhead[1]->sp = (u_long) root;
  816.         *--qhead[1]->sp = (u_long) (hook - TWO);
  817.  
  818. #if     !defined(M68K) && !defined(I386)
  819.         qhead[1]->sp = qhead[1]->sb;
  820. #endif  !M68K && !I386
  821.  
  822.         thno++;
  823.         free(buf);
  824.         sigsetmask(mask);
  825. }
  826.  
  827. void    tmove(u, v)
  828. u_long  u;
  829. u_long  v;
  830. {
  831.         if (qtail[v])
  832.             qtail[v]->next = qhead[u];
  833.         else qhead[v] = qhead[u];
  834.         qtail[v] = qhead[u];
  835.         qhead[u] = qhead[u]->next;
  836.         qtail[v]->next = NUL;
  837.         if (!qhead[u]) qtail[u] = NUL;
  838. }
  839.  
  840. Thread *twait(mask)
  841. int     mask;
  842. {
  843.         while (!qhead[1]) {
  844.             print1("[pid %d] waiting...\n", getpid());
  845.             sigpause(mask);
  846.         }
  847.         if (qhead[1]->mbuf)
  848.             tinit();
  849.         return qhead[1];
  850. }
  851.  
  852. u_long *cwait(n, v, hp, sp, pc)
  853. u_long  n;
  854. u_long  v;
  855. u_long *hp;
  856. u_long *sp;
  857. u_long *pc;
  858. {
  859.         int     mask;
  860.  
  861.         mask = sigblock(sigmask(SIGIO));
  862.         qhead[1]->sp = sp;
  863.         qhead[1]->pc = pc;
  864.         if (n == 0) {
  865.             qtail[1]->next = qhead[1];
  866.             qtail[1] = qhead[1];
  867.             qhead[1] = qhead[1]->next;
  868.             qtail[1]->next = NUL;
  869.         }
  870.         else {
  871.             qhead[1]->count = n;
  872.             tmove(1, v);
  873.         }
  874.         space.hp = hp;
  875.         *space.hp = (u_long) twait(mask);
  876.         sigsetmask(mask);
  877.         return space.hp;
  878. }
  879.  
  880. void    cpost(n, v)
  881. u_long  n;
  882. u_long  v;
  883. {
  884.         Thread *rhead = NUL;
  885.         Thread *rtail = NUL;
  886.         Thread *vhead = NUL;
  887.         Thread *vtail = NUL;
  888.         Thread *vtemp = qhead[v];
  889.         int     mask;
  890.  
  891.         if (n == 0) n = TNO;
  892.         if (vtemp)
  893.         do  if (n-- == 0) break;
  894.             else if (--vtemp->count == 0) {
  895.                 if (rtail)
  896.                     rtail->next = vtemp;
  897.                 else rhead = vtemp;
  898.                 rtail = vtemp;
  899.             }
  900.             else {
  901.                 if (vtail)
  902.                     vtail->next = vtemp;
  903.                 else vhead = vtemp;
  904.                 vtail = vtemp;
  905.             }
  906.         while (vtemp = vtemp->next);
  907.  
  908.         mask = sigblock(sigmask(SIGIO));
  909.         if (qtail[1])
  910.             qtail[1]->next = rhead;
  911.         else qhead[1] = rhead;
  912.         if (rtail) {
  913.             qtail[1] = rtail;
  914.             qtail[1]->next = NUL;
  915.         }
  916.         qhead[v] = vhead ? vhead : vtemp;
  917.         if (vtail) vtail->next = vtemp;
  918.         if (!vtemp) qtail[v] = vtail;
  919.         sigsetmask(mask);
  920. }
  921.  
  922. void    zero(ptr, n)
  923. u_long *ptr;
  924. u_long  n;
  925. {
  926.         for (n = n / 4; n > 0;)
  927.             ptr[--n] = 0L;
  928. }
  929.  
  930. char   *alloc(n)
  931. int     n;
  932. {
  933.         char *hp = (char *) space.hp;
  934.  
  935.         space.hp = (u_long *) (hp + n);
  936.         return hp;
  937. }
  938.  
  939. long    iceil(x)
  940. double  x;
  941. {
  942.         return ((long) ceil(x));
  943. }
  944.  
  945. long    ifloor(x)
  946. double  x;
  947. {
  948.         return ((long) floor(x));
  949. }
  950.  
  951. long    iround(x)
  952. double  x;
  953. {
  954.         return ((long) floor(x + 0.5));
  955. }
  956.  
  957. long    itrunca(x)
  958. double  x;
  959. {
  960.         return ((long) (x > 0.0 ? floor(x) : ceil(x)));
  961. }
  962.  
  963. double  ffloat(x)
  964. long    x;
  965. {
  966.         return ((double) x);
  967. }
  968.  
  969. u_long *dbug()
  970. {
  971.         fprintf(stderr, "I am in kernel dbug!\n");
  972. }
  973.  
  974.